package com.market.xg.gateway.service.route;

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.market.xg.common.starter.util.CommonUtils;
import com.market.xg.common.starter.util.JsonUtils;
import com.market.xg.gateway.event.DynamicRouteEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;

@Slf4j
@Component
public class DynamicRouteByNacos implements CommandLineRunner {

    @Autowired
    private DynamicRouteEvent dynamicRouteEvent;

    @Value("${dynamic.route.dataId:gateway-route}")
    private String dataId;

    @Value("${spring.cloud.nacos.config.group}")
    private String group;

    @Value("${spring.cloud.nacos.config.namespace}")
    private String namespace;

    @Value("${spring.cloud.nacos.config.server-addr}")
    private String serverAddr;

    @Value("${spring.cloud.nacos.config.timeout:3000}")
    private Long timeOut;

    @Override
    public void run(String... args) throws Exception {
        dynamicRouteByNacosListener();
    }

    private void dynamicRouteByNacosListener() {
        try {
            log.info("dynamicRouteByNacosListener");
            Properties properties = new Properties();
            properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
            properties.put(PropertyKeyConst.NAMESPACE, namespace);
            ConfigService configService = NacosFactory.createConfigService(properties);
            String config = configService.getConfig(dataId, group, timeOut);
            configService.addListener(dataId, group, new Listener() {
                @Override
                public Executor getExecutor() {
                    return null;
                }

                @Override
                public void receiveConfigInfo(String route) {
                    log.info("receiveConfigInfo route={}", route);
                    loadRoute(route);
                }
            });
            loadRoute(config);
            log.info("loadRoute init success");
        } catch (Exception e) {
            log.error("dynamicRouteByNacosListenerError", e);
        }

    }

    private void loadRoute(String route) {
        try {
            log.info("loadRoute route={}", route);
            if (CommonUtils.isNotEmpty(route)) {
                List<RouteDefinition> routeDefinitions = JsonUtils.deserializeList(route, RouteDefinition.class);
                routeDefinitions.forEach(routeDefinition -> {
                    dynamicRouteEvent.updateRoute(routeDefinition);
                });
            }
        } catch (Exception e) {
            log.error("loadRouteError", e);
        }
    }
}
